#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <SoftwareSerial.h>
#include <WString.h>

#define FS_CONFIG
//兼容1.1.x版本库
#include <../lib/wifiLink/wifi_link_tool.h>
#include <../lib/ArduinoJson/ArduinoJson.h>
#include <../lib/U8g2/src/U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI

#include <SPI.h>

#endif
#ifdef U8X8_HAVE_HW_I2C

#include <Wire.h>

#endif

#include "zlt.h"
#include "Defines.h"

String server = "mengxingiot.com";
uint16_t port = 8282;
String ok = "ok";
String err = "err";
String ping = "ping";
WiFiClient client;
SoftwareSerial serialPort(D5, D6);

/**
 * 业务逻辑处理函数
 * */
void domain(int form, int to, const char *cmd) {
    Serial.println(form);
    Serial.println(to);
    Serial.println(cmd);
    if (to == deviceId) {
//        todo: do some things
    }

}

void setup() {
    Serial.begin(115200);
    serialPort.begin(9600);
    rstb = D7;
    /* 重置io */
    stateled = D4;
    /* 指示灯io */
    Hostname = "infusionNode";
    /* 设备名称 允许中文名称 不建议太长 */
    wxscan = false;
    /* 是否被小程序发现设备 开启意味该设备具有后台 true开启 false关闭 */
    pinMode(statusPin, INPUT);
    pinMode(temperaturePin, INPUT);
    pinMode(lockMotorA, OUTPUT);
    pinMode(lockMotorB, OUTPUT);
    pinMode(lockResetPin, INPUT_PULLUP);
    pinMode(buzzerPin, OUTPUT);
    /* 初始化WiFi link tool */
    load();

    if (link()) {

    } else {

    }
}


void loop() {
    /**
     * WiFi link tool 服务维持函数  请勿修改位置
     * */
    pant();
    if (link() && !client.connected()) {
        connectToTheServer();
    }
    msgHandler(readMsgFormServer());
//    发送初始状态信息
    sendToTheServer(111112, "infusion*45465*72*23");
    if (digitalRead(statusPin) == HIGH) {
//        输液完成发送状态信息
        sendToTheServer(111112, "complete*45465*0*23");
        delay(500);
//        发送完成提示音指令
        sendToTheServer(111112, "completionPrompt");
//        触发锁止
        digitalWrite(lockMotorA, HIGH);
        digitalWrite(lockMotorB, LOW);
//        使用时间原则控制电机行程
        delay(300);
        digitalWrite(lockMotorA, LOW);
        digitalWrite(lockMotorB, LOW);
//        蜂鸣器报警三声
        digitalWrite(buzzerPin, HIGH);
        delay(800);
        digitalWrite(buzzerPin, LOW);
        delay(800);
        digitalWrite(buzzerPin, HIGH);
        delay(800);
        digitalWrite(buzzerPin, LOW);
        delay(800);
        digitalWrite(buzzerPin, HIGH);
        delay(800);
        digitalWrite(buzzerPin, LOW);
        delay(800);
    }
//    重置按钮触发
    if (digitalRead(lockResetPin) == LOW) {
        sendToTheServer(111112, "infusion*45465*72*23");
        delay(500);
        sendToTheServer(111112, "beginPrompt");
        //        复位锁止
        digitalWrite(lockMotorB, HIGH);
        digitalWrite(lockMotorA, LOW);
//        使用时间原则控制电机行程
        delay(300);
        digitalWrite(lockMotorA, LOW);
        digitalWrite(lockMotorB, LOW);
    }
}

/**
 * 从服务器读取信息
 * 阻塞读
 * */
String readMsgFormServer() {
    String data = "";
    while (client.available() > 0) {
        data += client.readStringUntil('\n');
        delay(2);
    }
    data.trim();
    return data;
}

/**
 * 信息处理
 * */
void msgHandler(String data) {
//    排除服务端心跳和空响应
    if (data.isEmpty()) {
        return;
    }

    if (data.compareTo(ping) == 0) {
        Serial.println("PING" + data);
        return;
    }
    if (data.compareTo(ok) == 0) {
        Serial.println("OK" + data);
        return;
    }
    if (data.compareTo(err) == 0) {
        Serial.println("ERR" + data);
        return;
    }

    Serial.println("decode data:" + data);
//开始处理业务逻辑
    DynamicJsonDocument doc(100);
    DeserializationError error = deserializeJson(doc, data);
    if (error) {
        doc.clear();
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.c_str());
//        发生致命错误延时2秒重启
//        delay(2000);
//        ESP.restart();
    }
    JsonVariant form, to, cmd;
    form = doc.getMember("form");
    to = doc.getMember("to");
    cmd = doc.getMember("cmd");
    int _form = form.as<int>();
    int _to = to.as<int>();
    const char *_cmd = cmd.as<char *>();
//    回收内存
    doc.clear();
    form.clear();
    to.clear();
    cmd.clear();
    domain(_form, _to, _cmd);
}

void connectToTheServer() {
    client.connect(server, port);
    delay(500);
    String connectStatus = readMsgFormServer();
    if (connectStatus.compareTo(ok) == 0) {
//        连接服务器成功
        sendToTheServer(111111, "login");
//        200ms后清空缓冲区
        delay(500);
        String loginStatus = readMsgFormServer();
        if (loginStatus.compareTo(ok) == 0) {
//            登录服务器成功
        } else {
//            登录服务器失败
        }
    } else {
//       连接服务器失败
    }
}

size_t sendToTheServer(int to, const char *cmd) {
    StaticJsonDocument<100> doc;
    doc["form"] = deviceId;
    doc["to"] = to;
    doc["cmd"] = cmd;
    String data;
    size_t rs = 0;
    serializeJson(doc, data);
    if (client.availableForWrite()) {
        Serial.println("send:" + data);
        rs = client.println(data);
        doc.clear();
        return rs;
    }
    doc.clear();
    return rs;
}
